package com.gitee.cui.basic.producerandconsumer;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 数据缓冲区，安全版本的定义
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/11/19 14:23
 **/
@Slf4j
public class SafeDataBuffer<T> {

    private static final int MAX_AMOUT = 10;

    private List<T> dataList = new LinkedList<>();

    private AtomicInteger amount = new AtomicInteger(0);

    /**
     * 向数据区增加要给元素
     * @param element 需要增加的元素
     */
    public synchronized void add(T element) throws Exception {
        // 先进行校验，校验不通过，直接返回
        if (amount.get() > MAX_AMOUT) {
            log.info("队列已经满了！");
            return;
        }

        dataList.add(element);
        log.info("向队列中添加元素：{}", element);
        amount.incrementAndGet();

        // 再进行校验，如果校验不通过，抛出异常
        if (amount.get() != dataList.size()) {
            throw new Exception(amount + "!=" + dataList.size());
        }
    }

    /**
     * 从数据区中取出一个元素
     * @return 数据区中的元素
     */
    public synchronized T fetch() throws Exception {
        // 先进行校验，如果检验不通过，直接返回
        if (amount.get() <= 0) {
            log.info("队列已经空了！");
            return null;
        }
        T element = null;
        if (dataList.size() > 0) {
            element = dataList.remove(0);
            log.info("从队列中取出元素：{}", element);
        }
        amount.decrementAndGet();

        // 再次进行校验，如果校验失败，抛出异常
        if (amount.get() != dataList.size()) {
            throw new Exception(amount + "!=" + dataList.size());
        }
        return element;
    }
}
